package com.dhecp.project.flowable.service.impl;

import com.dhecp.common.core.domain.AjaxResult;
import com.dhecp.common.utils.MessageUtils;
import com.dhecp.common.utils.StringUtils;
import com.dhecp.common.utils.TypeUtils;
import com.dhecp.core.constant.FlowableConstant;
import com.dhecp.framework.util.CustomFunctionUtils;
import com.dhecp.framework.util.ShiroUtils;
import com.dhecp.project.flowable.cmd.AddTaskCommentCmd;
import com.dhecp.project.flowable.cmd.JumpTaskCommand;
import com.dhecp.project.flowable.cmd.RollbackTaskCmd;
import com.dhecp.project.flowable.cmd.UpdateHiTaskReasonCommand;
import com.dhecp.project.flowable.domain.ActHistoricTask;
import com.dhecp.project.flowable.domain.ActRuntimeTask;
import com.dhecp.project.flowable.domain.ActSimpleActivity;
import com.dhecp.project.flowable.domain.SysProcessInstance;
import com.dhecp.project.flowable.extend.FlowableUtils;
import com.dhecp.project.flowable.juel.ActAuthService;
import com.dhecp.project.flowable.mapper.ActProcessMapper;
import com.dhecp.project.flowable.mapper.SysProcessInstanceMapper;
import com.dhecp.project.flowable.service.ActProcessService;
import com.dhecp.project.flowable.service.ActProcessTaskService;
import com.dhecp.project.system.domain.SysUserInfoSimple;
import com.dhecp.project.system.mapper.SysUserInfoMapper;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl;
import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext;
import org.flowable.common.engine.impl.javax.el.ExpressionFactory;
import org.flowable.common.engine.impl.javax.el.ValueExpression;
import org.flowable.engine.*;
import org.flowable.engine.impl.bpmn.behavior.*;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName ActProcessTaskServiceImpl
 * @Description TODO
 * @Author alula
 * @Date 2020-04-01 14:57
 */
@Service
public class ActProcessTaskServiceImpl implements ActProcessTaskService {
    private static final Logger log = LoggerFactory.getLogger(ActProcessTaskServiceImpl.class);

    @Autowired
    private TaskService taskService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ManagementService managementService;

    @Autowired
    private IdentityService identityService;

    @Autowired
    private SysUserInfoMapper sysUserInfoMapper;

    @Autowired
    private SysProcessInstanceMapper sysProcessInstanceMapper;

    @Autowired
    private ActProcessService actProcessService;

    @Autowired
    private CustomFunctionUtils customFunctionUtils;

    @Autowired
    private ActProcessMapper actProcessMapper;

    @Override
    public List<ActRuntimeTask> queryTodoActRuntimeTask(Map<String, Object> params) {
        params.put("assignee", ShiroUtils.getMandatorId());
        return actProcessMapper.findActTodoRuntimeTask(params);
    }

    @Override
    public List<ActHistoricTask> queryDoneActHistoricTask(Map<String, Object> params) {
        params.put("assignee", ShiroUtils.getMandatorId());
        List<ActHistoricTask> taskList = actProcessMapper.findActDoneRuntimeTask(params);
        return taskList;
    }

    @Override
    public SysProcessInstance querySysProcessInstanceByTableDataId(String tableDataId) {
        return sysProcessInstanceMapper.findSysProcessInstanceByTableDataId(tableDataId);
    }

    @Override
    public Task queryTaskById(String taskId) {
        return taskService.createTaskQuery().taskId(taskId).singleResult();
    }

    @Override
    public ProcessInstance queryProcessInstanceByInstId(String instId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(instId).singleResult();
        return processInstance;
    }

    @Override
    public FlowElement queryCurrentTaskPrevActivity(String taskId, String currActId) {
        FlowElement targetActivity = null;
        Task currentTask = queryTaskById(taskId);
        if (currentTask == null) {
            return targetActivity;
        }
        //20200413取上一个退回环节，采用跟驳回方法一致，取最近一个环节
        org.flowable.bpmn.model.Process process = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId()).getMainProcess();
        FlowNode currentFlowElement = (FlowNode) process.getFlowElement(currActId, true);
        List<ActivityInstance> activitys = runtimeService.createActivityInstanceQuery().processInstanceId(currentTask.getProcessInstanceId()).finished().orderByActivityInstanceStartTime().asc().list();
        List<String> activityIds = activitys.stream()
                .filter(activity -> activity.getActivityType().equals(BpmnXMLConstants.ELEMENT_TASK_USER))
                .filter(activity -> !activity.getActivityId().equals(currActId)).map(ActivityInstance::getActivityId)
                .distinct().collect(Collectors.toList());
        List<FlowNode> flowNodeList = new ArrayList<>();
        for (String activityId : activityIds) {
            FlowNode toBackFlowElement = (FlowNode) process.getFlowElement(activityId, true);
            if (FlowableUtils.isReachable(process, toBackFlowElement, currentFlowElement)) {
                flowNodeList.add(toBackFlowElement);
            }
        }
        if(flowNodeList.size() > 0){
            targetActivity = flowNodeList.get(flowNodeList.size() -1);
        }
        return targetActivity;
    }

    @Override
    public FlowElement queryCurrentTaskNextActivity(String taskId) {
        FlowElement targetActivity = null;
        Task currentTask = queryTaskById(taskId);
        if (currentTask == null) {
            return targetActivity;
        }
        Map<String, Object> mapVars = taskService.getVariables(taskId);
        org.flowable.bpmn.model.Process process = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId()).getMainProcess();
        FlowNode currentFlowElement = (FlowNode) process.getFlowElement(currentTask.getTaskDefinitionKey(), true);
        // 当前节点的流出来源

        List<SequenceFlow> sequenceFlows = currentFlowElement.getOutgoingFlows();
        for (SequenceFlow sequenceFlow : sequenceFlows) {
            String targetRef = sequenceFlow.getTargetRef();
            FlowElement sequenceFlowTarget = process.getFlowElement(targetRef, true);
            if (sequenceFlowTarget instanceof StartEvent){
                targetActivity = (FlowNode)sequenceFlowTarget;
            }else if (sequenceFlowTarget instanceof EndEvent){
                targetActivity = (FlowNode)sequenceFlowTarget;
            }else if (sequenceFlowTarget instanceof UserTask){
                targetActivity = (FlowNode)sequenceFlowTarget;
            }else if (sequenceFlowTarget instanceof Gateway){//为网关节点走这边
                targetActivity = recursionGetTaskNextActivity(process, (FlowNode)sequenceFlowTarget, sequenceFlowTarget.getId(), currentTask.getProcessInstanceId(), mapVars);
            }else{
                targetActivity = (FlowNode)sequenceFlowTarget;
            }
        }
        return targetActivity;
    }

    @Override
    public List<SysUserInfoSimple> queryPrevTaskCandidateUsers(String proInsId, FlowElement prevActivity) {
        List<String> userList = new ArrayList<>();
        List<SysUserInfoSimple> userInfoList = new ArrayList<SysUserInfoSimple>();
        if(prevActivity == null){
            return  userInfoList;
        }
        if (prevActivity instanceof ParallelGateway) { //判断是否为并行网关
            List<SequenceFlow> sequenceFlowList = ((ParallelGateway) prevActivity).getIncomingFlows();
            for (SequenceFlow sequenceFlow : sequenceFlowList) {
                FlowNode sourceFlowNode = (FlowNode) sequenceFlow.getTargetFlowElement();
                //20200710加上原因条件，只取原因为“completed”的历史任务数据
                List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(proInsId).taskDefinitionKey(sourceFlowNode.getId()).taskDeleteReason(FlowableConstant.PASSED_FLAG).finished().orderByHistoricTaskInstanceEndTime().desc().list();
                if (historicTaskInstanceList != null && historicTaskInstanceList.size() > 0) {
                    for (HistoricTaskInstance historicTaskInstance : historicTaskInstanceList) {
                        if (!StringUtils.isEmpty(historicTaskInstance.getAssignee()) && !userList.equals(historicTaskInstance.getAssignee())) {
                            userList.add(historicTaskInstance.getAssignee());
                        }
                        //20200413去掉取ACT_HI_IDENTITYLINK去掉，historicTaskInstance.getAssignee()已经有指定人了
                    /*List<HistoricIdentityLink> historicIdentityLinks = historyService.getHistoricIdentityLinksForTask(historicTaskInstance.getId());
                    for (HistoricIdentityLink historicIdentityLink : historicIdentityLinks) {
                        if(!StringUtils.isEmpty(historicIdentityLink.getUserId()) && !historicIdentityLink.getType().equals(IdentityLinkType.OWNER) && !historicIdentityLink.getType().equals(FlowableConstant.EXECUTOR_TYPE) && !userList.equals(historicIdentityLink.getUserId())) {//去掉actualExecutor类型数据
                            userList.add(historicIdentityLink.getUserId());
                        }
                    }*/
                    }
                }

            }
        } else {
            //20200710加上原因条件，只取原因为“completed”的历史任务数据
            List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(proInsId).taskDefinitionKey(prevActivity.getId()).taskDeleteReason(FlowableConstant.PASSED_FLAG).finished().orderByHistoricTaskInstanceEndTime().desc().list();
            if (historicTaskInstanceList != null && historicTaskInstanceList.size() > 0) {
                HistoricTaskInstance tempHistoricTaskInstance = null;
                int k = 1;
                for (HistoricTaskInstance historicTaskInstance : historicTaskInstanceList) {
                    tempHistoricTaskInstance = historicTaskInstance;
                    FlowElement activity = queryActivitiImplByProDefIdandActId(historicTaskInstance.getProcessDefinitionId(), historicTaskInstance.getTaskDefinitionKey());
                    //activity.getProperty("multiInstance") == null判断多人会签
                    if (!(((FlowNode) activity).getBehavior() instanceof MultiInstanceActivityBehavior) && tempHistoricTaskInstance.getTaskDefinitionKey().equals(historicTaskInstance.getTaskDefinitionKey()) && k > 1) {
                        continue;
                    }
                    if (!StringUtils.isEmpty(historicTaskInstance.getAssignee()) && !userList.equals(historicTaskInstance.getAssignee())) {
                        userList.add(historicTaskInstance.getAssignee());
                    }
                    //20200413去掉取ACT_HI_IDENTITYLINK去掉，historicTaskInstance.getAssignee()已经有指定人了
                    /*List<HistoricIdentityLink> historicIdentityLinks = historyService.getHistoricIdentityLinksForTask(historicTaskInstance.getId());
                    for (HistoricIdentityLink historicIdentityLink : historicIdentityLinks) {
                      if(!StringUtils.isEmpty(historicIdentityLink.getUserId()) && !historicIdentityLink.getType().equals(IdentityLinkType.OWNER) && !historicIdentityLink.getType().equals(FlowableConstant.EXECUTOR_TYPE) && !userList.equals(historicIdentityLink.getUserId())) {//去掉actualExecutor类型数据
                         userList.add(historicIdentityLink.getUserId());
                      }
                    }*/
                    k++;
                }
            }
        }
        userInfoList = customFunctionUtils.queryActivitiNextUser(userList, null, "", null);
        return userInfoList;
    }

    @Override
    public List<SysUserInfoSimple> queryNextTaskCandidateUsers(String procDefId, String taskId, FlowElement nextActivity, boolean isParallelGatewayInnerUserTask) {
        List<String> userList = new ArrayList<>();
        List<String> roleList = new ArrayList<>();
        List<SysUserInfoSimple> userInfoList = new ArrayList<SysUserInfoSimple>();
        String customType = "";
        String customDataCandidate = "";
        if(isParallelGatewayInnerUserTask == true){//判断是否为并行网关内的节点，是取所有并行网关用用户环节的用户
            org.flowable.bpmn.model.Process process = repositoryService.getBpmnModel(procDefId).getMainProcess();
            Map<String, Set<String>> specialGatewayNodes = FlowableUtils.getSpecialGatewayElements(process);
            if(specialGatewayNodes != null && specialGatewayNodes.size() > 0){
                for(Map.Entry<String, Set<String>> entry : specialGatewayNodes.entrySet()){
                    String mapKey = entry.getKey();
                    Set<String> specialGatewayList = (Set<String>)specialGatewayNodes.get(mapKey);
                    for (String item : specialGatewayList) {
                        FlowNode flowNode = (FlowNode) process.getFlowElement(item, true);
                        if(flowNode instanceof  UserTask){
                            UserTask userTaskNode = (UserTask)flowNode;
                            if (userTaskNode != null) {
                                if (!StringUtils.isEmpty(userTaskNode.getAssignee())) {
                                    userList.add(userTaskNode.getAssignee());
                                }
                                List<String> userExpressions = userTaskNode.getCandidateUsers();
                                if (userExpressions != null && userExpressions.size() > 0) {
                                    for (String userId : userExpressions) {
                                        userList.add(userId);
                                    }
                                }
                                List<String> roleExpressions = userTaskNode.getCandidateGroups();
                                if (roleExpressions != null && roleExpressions.size() > 0) {
                                    for (String groupId : roleExpressions) {
                                        roleList.add(groupId);
                                    }
                                }
                                String formKeyExpression = userTaskNode.getFormKey();
                                if (!StringUtils.isEmpty(formKeyExpression)) {
                                    customType = formKeyExpression;
                                }
                                Map<String, List<ExtensionAttribute>> extensionAttrs = userTaskNode.getAttributes();
                                if(extensionAttrs != null  && extensionAttrs.size() > 0){
                                    List<ExtensionAttribute> extensionAttributeList = extensionAttrs.get(FlowableConstant.CUSTOM_DATA_CANDIDATE_KEY);
                                    if(extensionAttributeList != null && extensionAttributeList.size() > 0){
                                        customDataCandidate = extensionAttributeList.get(0).getValue();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }else {
            if (nextActivity != null) {
                if (nextActivity instanceof EndEvent) {// 到结束环节，人员直接返回[]
                    return userInfoList;
                } else if (nextActivity instanceof UserTask) {//为userTask环节类型
                    FlowNode actFlowNode = (FlowNode) nextActivity;
                    if (actFlowNode.getBehavior() instanceof ParallelMultiInstanceBehavior) {
                        ParallelMultiInstanceBehavior parallelBehavior = (ParallelMultiInstanceBehavior) actFlowNode.getBehavior();
                        Expression expression = parallelBehavior.getCollectionExpression();
                        String collectionVal = "";
                        if (expression != null) {
                            collectionVal = expression.getExpressionText();
                        }
                        List<String> collectionUsers = (List<String>) taskService.getVariable(taskId, collectionVal);
                        for (String item : collectionUsers) {
                            if (!StringUtils.isEmpty(item)) {
                                userList.add(item);
                            }
                        }
                    }
                    if (actFlowNode.getBehavior() instanceof SequentialMultiInstanceBehavior) {
                        SequentialMultiInstanceBehavior sequentialBehavior = (SequentialMultiInstanceBehavior) actFlowNode.getBehavior();
                        Expression expression = sequentialBehavior.getCollectionExpression();
                        String collectionVal = "";
                        if (expression != null) {
                            collectionVal = expression.getExpressionText();
                        }
                        List<String> collectionUsers = (List<String>) taskService.getVariable(taskId, collectionVal);
                        for (String item : collectionUsers) {
                            if (!StringUtils.isEmpty(item)) {
                                userList.add(item);
                            }
                        }
                    }
                    UserTask userTaskNode = (UserTask) nextActivity;
                    if (userTaskNode != null) {
                        if (!StringUtils.isEmpty(userTaskNode.getAssignee())) {
                            userList.add(userTaskNode.getAssignee());
                        }
                        List<String> userExpressions = userTaskNode.getCandidateUsers();
                        if (userExpressions != null && userExpressions.size() > 0) {
                            for (String userId : userExpressions) {
                                userList.add(userId);
                            }
                        }
                        List<String> roleExpressions = userTaskNode.getCandidateGroups();
                        if (roleExpressions != null && roleExpressions.size() > 0) {
                            for (String groupId : roleExpressions) {
                                roleList.add(groupId);
                            }
                        }
                        String formKeyExpression = userTaskNode.getFormKey();
                        if (!StringUtils.isEmpty(formKeyExpression)) {
                            customType = formKeyExpression;
                        }
                        Map<String, List<ExtensionAttribute>> extensionAttrs = userTaskNode.getAttributes();
                        if(extensionAttrs != null  && extensionAttrs.size() > 0){
                            List<ExtensionAttribute> extensionAttributeList = extensionAttrs.get(FlowableConstant.CUSTOM_DATA_CANDIDATE_KEY);
                            if(extensionAttributeList != null && extensionAttributeList.size() > 0){
                                customDataCandidate = extensionAttributeList.get(0).getValue();
                            }
                        }
                    }
                } else if (nextActivity instanceof ParallelGateway) {//parallelGateway并行网关，执行人要取分支中的环节对应的人
                    List<SequenceFlow> sequenceFlowList = ((ParallelGateway) nextActivity).getOutgoingFlows();
                    for (SequenceFlow sequenceFlow : sequenceFlowList) {
                        FlowNode targetFlowNode = (FlowNode) sequenceFlow.getTargetFlowElement();
                        if (targetFlowNode != null && targetFlowNode instanceof UserTask) {
                            UserTask userTaskNode = (UserTask) targetFlowNode;
                            if (userTaskNode != null) {
                                if (!StringUtils.isEmpty(userTaskNode.getAssignee())) {
                                    userList.add(userTaskNode.getAssignee());
                                }
                                List<String> userExpressions = userTaskNode.getCandidateUsers();
                                if (userExpressions != null && userExpressions.size() > 0) {
                                    for (String userId : userExpressions) {
                                        userList.add(userId);
                                    }
                                }
                                List<String> roleExpressions = userTaskNode.getCandidateGroups();
                                if (roleExpressions != null && roleExpressions.size() > 0) {
                                    for (String groupId : roleExpressions) {
                                        roleList.add(groupId);
                                    }
                                }
                                String formKeyExpression = userTaskNode.getFormKey();
                                if (!StringUtils.isEmpty(formKeyExpression)) {
                                    customType = formKeyExpression;
                                }
                                Map<String, List<ExtensionAttribute>> extensionAttrs = userTaskNode.getAttributes();
                                if(extensionAttrs != null && extensionAttrs.size() > 0){
                                    List<ExtensionAttribute> extensionAttributeList = extensionAttrs.get(FlowableConstant.CUSTOM_DATA_CANDIDATE_KEY);
                                    if(extensionAttributeList != null && extensionAttributeList.size() > 0){
                                        customDataCandidate = extensionAttributeList.get(0).getValue();
                                    }
                                }
                            }

                        }
                    }
                }//type
                //}
            }//activity
        }
        Map<String, Object> moduleInfoMap = null;
        Map<String, Object> mapVars = taskService.getVariables(taskId);
        if(mapVars != null && !StringUtils.isEmpty(customDataCandidate)){
            moduleInfoMap = new HashMap<>();
            moduleInfoMap.put("moduleTable", mapVars.get("moduleKey"));
            moduleInfoMap.put("moduleNid", mapVars.get("tableDataId"));
            moduleInfoMap.put("userId", ShiroUtils.getMandatorId());
            moduleInfoMap.put("cType", customDataCandidate);
        }
        userInfoList = customFunctionUtils.queryActivitiNextUser(userList, roleList, customType, moduleInfoMap);
        return userInfoList;
    }

    /**
     *递归获取任务下一个节点对象, 
     * @param process
     * @param flowNode
     * @param activityId
     * @param processInstanceId
     * @param mapVars
     * @return
     */
    private FlowNode recursionGetTaskNextActivity(org.flowable.bpmn.model.Process process, FlowNode flowNode, String activityId, String processInstanceId,Map<String, Object> mapVars) {
        FlowNode ac = null;
        Object s = null;
        // 如果遍历节点为用户任务并且节点不是当前节点信息
        if (flowNode instanceof  UserTask && !activityId.equals(flowNode.getId())) {
            // 获取该节点下一个节点信息
            if (flowNode.getBehavior() instanceof UserTaskActivityBehavior) {
                UserTaskActivityBehavior aaBehavior = (UserTaskActivityBehavior)flowNode.getBehavior();
                return flowNode;
            } else if (flowNode.getBehavior() instanceof ParallelMultiInstanceBehavior) {
                ParallelMultiInstanceBehavior aaBehavior = (ParallelMultiInstanceBehavior)flowNode.getBehavior();
                return flowNode;
            }else if (flowNode.getBehavior() instanceof SequentialMultiInstanceBehavior) {
                SequentialMultiInstanceBehavior aaBehavior = (SequentialMultiInstanceBehavior)flowNode.getBehavior();
                return flowNode;
            }
        } else if (flowNode instanceof  ExclusiveGateway) {//是否是排斥网关
            List<SequenceFlow> outTransitions = flowNode.getOutgoingFlows();
            // 如果排他网关只有一条线路信息
            if (outTransitions.size() == 1) {
                FlowElement targetFlowElement1 = outTransitions.get(0).getTargetFlowElement();
                return recursionGetTaskNextActivity(process, (FlowNode) targetFlowElement1, activityId, processInstanceId, mapVars);
            } else if (outTransitions.size() > 1) { // 如果排他网关有多条线路信息
                for (SequenceFlow tr1 : outTransitions) {
                    s = tr1.getConditionExpression(); // 获取排他网关线路判断条件信息
                    // 判断el表达式是否成立
                    if (isCondition(flowNode.getId(), StringUtils.trim(s.toString()), mapVars)) {
                        FlowElement targetFlowElement2 = tr1.getTargetFlowElement();
                        return recursionGetTaskNextActivity(process, (FlowNode)targetFlowElement2, activityId, processInstanceId, mapVars);
                    }
                }
            }
        } else if (flowNode instanceof  ParallelGateway) {//是否是并行网关
            List<SequenceFlow> outTransitions = flowNode.getOutgoingFlows();
            if (outTransitions.size() == 1) {
                FlowElement targetFlowElement1 = outTransitions.get(0).getTargetFlowElement();
                if(targetFlowElement1 instanceof UserTask){
                    return (FlowNode)targetFlowElement1;
                }else {
                    return recursionGetTaskNextActivity(process, (FlowNode) targetFlowElement1, activityId, processInstanceId, mapVars);
                }
            } else if (outTransitions.size() > 1) { // 如果并行网关有多条线路信息
                for (SequenceFlow sequenceFlow2 : outTransitions) {
                    FlowElement targetFlowElement2 = sequenceFlow2.getTargetFlowElement();
                    if(targetFlowElement2 instanceof UserTask){
                        return (FlowNode)targetFlowElement2;
                    }else {
                        return recursionGetTaskNextActivity(process, (FlowNode) targetFlowElement2, activityId, processInstanceId, mapVars);
                    }
                }
            }
        }else {
            // 获取节点所有流向线路信息
            List<SequenceFlow> outTransitions = flowNode.getOutgoingFlows();
            List<SequenceFlow> outTransitionsTemp = null;
            if(outTransitions != null && outTransitions.size() > 0) {
                for (SequenceFlow tr : outTransitions) {
                    ac = (FlowNode)tr.getTargetFlowElement();
                    // 如果流向线路为排他网关
                    if (flowNode instanceof  ExclusiveGateway) {
                        outTransitionsTemp = ac.getOutgoingFlows();
                        // 如果排他网关只有一条线路信息
                        if (outTransitionsTemp.size() == 1) {
                            FlowElement targetTempFlowElement1 = outTransitionsTemp.get(0).getTargetFlowElement();
                            return recursionGetTaskNextActivity(process, (FlowNode)targetTempFlowElement1, activityId,
                                    processInstanceId, mapVars);
                        } else if (outTransitionsTemp.size() > 1) { // 如果排他网关有多条线路信息
                            for (SequenceFlow tr1 : outTransitionsTemp) {
                                s = tr1.getConditionExpression(); // 获取排他网关线路判断条件信息
                                // 判断el表达式是否成立
                                if (isCondition(ac.getId(), StringUtils.trim(s.toString()), mapVars)) {
                                    FlowElement targetTempFlowElement2 = tr1.getTargetFlowElement();
                                    return recursionGetTaskNextActivity(process, (FlowNode)targetTempFlowElement2, activityId,
                                            processInstanceId, mapVars);
                                }
                            }
                        }
                    } else if (flowNode instanceof  UserTask) {
                        if (ac.getBehavior() instanceof UserTaskActivityBehavior) {
                            UserTaskActivityBehavior aaBehavior = (UserTaskActivityBehavior)ac.getBehavior();
                            return ac;
                        } else if (ac.getBehavior() instanceof ParallelMultiInstanceBehavior) {
                            ParallelMultiInstanceBehavior aaBehavior = (ParallelMultiInstanceBehavior)ac.getBehavior();
                            return ac;
                        }else if (ac.getBehavior() instanceof SequentialMultiInstanceBehavior) {
                            SequentialMultiInstanceBehavior aaBehavior = (SequentialMultiInstanceBehavior) ac.getBehavior();
                            return ac;
                        }
                    } else if (ac instanceof StartEvent) {
                        return ac;
                    } else if (ac instanceof EndEvent) {
                        return ac;
                    } else {
                        return ac;
                    }
                }
            }else{
                return flowNode;
            }
        }
        return null;
    }

    @Override
    public int queryUserCurrentInstanceRunTaskCount(String proInsId, String userId) {
        Map<String, Object> params = new HashMap<>();
        params.put("procInstId", proInsId);
        params.put("userId", userId);
        int result =  actProcessMapper.findTaskCountByUserId(params);
        return result;
    }

    @Override
    public Task queryUserCurrentInstanceRunTask(String proInsId, String userId) {
        Task task = taskService.createTaskQuery().processInstanceId(proInsId).taskAssignee(userId).singleResult();
        return  task;
    }

    @Override
    public FlowElement queryActivitiImplByProDefIdandActId(String proDefId, String activityId) {
        org.flowable.bpmn.model.Process process = repositoryService.getBpmnModel(proDefId).getMainProcess();
        FlowNode currentFlowElement = (FlowNode) process.getFlowElement(activityId, true);
        return currentFlowElement;
    }

    @Override
    public List<ActSimpleActivity> queryRejectActivityList(String proDefId, String proInsId, String taskId, String currActId) {
        List<ActSimpleActivity> activityList = new ArrayList<>();
        if(!StringUtils.isEmpty(taskId)) {
            Task currentTask = queryTaskById(taskId);
            if (currentTask == null) {
                return activityList;
            }
        }
        org.flowable.bpmn.model.Process process = repositoryService.getBpmnModel(proDefId).getMainProcess();
        FlowNode currentFlowElement = (FlowNode) process.getFlowElement(currActId, true);
        List<ActivityInstance> activitys = runtimeService.createActivityInstanceQuery().processInstanceId(proInsId).finished().orderByActivityInstanceStartTime().asc().list();
        List<String> activityIds = activitys.stream()
                .filter(activity -> activity.getActivityType().equals(BpmnXMLConstants.ELEMENT_TASK_USER))
                .filter(activity -> !activity.getActivityId().equals(currActId)).map(ActivityInstance::getActivityId)
                .distinct().collect(Collectors.toList());
        for (String activityId : activityIds) {
            FlowNode toBackFlowElement = (FlowNode) process.getFlowElement(activityId, true);
            if (FlowableUtils.isReachable(process, toBackFlowElement, currentFlowElement)) {
                ActSimpleActivity actSimpleActivity = new ActSimpleActivity();
                actSimpleActivity.setKey(activityId);
                actSimpleActivity.setName(toBackFlowElement.getName());
                activityList.add(actSimpleActivity);
            }
        }
        return activityList;
    }

    @Override
    public long queryCurrentUserTodoActRuntimeTaskCount(int filterEcpTask) {
        String userId = ShiroUtils.getMandatorId();
        Map<String, Object> params = new HashMap<>();
        params.put("procInstId", "");
        params.put("userId", userId);
        params.put("filterEcpTask", filterEcpTask);
        long count =  actProcessMapper.findTaskCountByUserId(params);
        return count;
    }

    @Override
    public AjaxResult passProcess(String taskId, Integer priority, String comment, List<String> assignees, Map<String, Object> variables, String medium, String softType) {
        if (StringUtils.isEmpty(taskId)) {
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "taskId"));
        }
        Task currentTask = queryTaskById(taskId);
        if (currentTask == null) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        if (currentTask.isSuspended() == true){
            return AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
        }
        ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult();
        if (instance == null) {
            return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        SysProcessInstance sysProcessInstance = sysProcessInstanceMapper.findSysProcessInstanceByGuid(instance.getBusinessKey());
        if (sysProcessInstance == null) {
            return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        FlowElement nextActivity = queryCurrentTaskNextActivity(taskId);
        String activityType = "";
        if (nextActivity != null) {
            activityType = FlowableUtils.getFlowElementType(nextActivity);
        }
        // 下一环节不是结束环节需要判断一个执行者不能为空
        if (!"endEvent".contains(activityType) && assignees == null || assignees.size() == 0) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskassigneesfail"));
        }
        if (StringUtils.isEmpty(comment) || "null".contains(comment)) {
            comment = "同意";
        }
        //20220127创建流程备注改成自已写的命令
        //taskService.addComment(taskId, currentTask.getProcessInstanceId(), comment);
        managementService.executeCommand(new AddTaskCommentCmd(taskId, currentTask.getProcessInstanceId(), comment));
        // 未解决的委托任务先resolve
        if (StringUtils.isNotEmpty(currentTask.getOwner()) && !("RESOLVED").equals(currentTask.getDelegationState().toString())) {
            taskService.resolveTask(taskId, variables);
        }
        // 接收任务(20200208当任务没有转办(owner为空)，才运行接收任务claim，已转办不接收，已转办人为准)
        if (StringUtils.isEmpty(currentTask.getOwner())) {
            taskService.claim(taskId, ShiroUtils.getMandatorId());
        }
        String nextActAlias = "";
        // 设置上环节与下环节的信息
        if (nextActivity != null) {
            sysProcessInstance.setPrevActId(currentTask.getTaskDefinitionKey());
            sysProcessInstance.setNextActId(nextActivity.getId());
            nextActAlias = getActivityAlias(nextActivity);
            sysProcessInstance.setNextActAlias(nextActAlias);
        }
        // 提交在deleteReason字段中标记
        managementService.executeCommand(new UpdateHiTaskReasonCommand(taskId, FlowableConstant.PASSED_FLAG));
        // 提交自已的任务
        if (variables == null) {
            variables = new HashMap<String, Object>();
        }
        variables = taskService.getVariables(taskId);
        variables.put("currentUserId", ShiroUtils.getMandatorId());
        taskService.complete(taskId, variables);
        // 获取下个环节的任务
        String nextTaskId = "";
        List<Task> nextTasks = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).list();
        if (nextTasks != null && nextTasks.size() > 0) {
            for (Task taskObj : nextTasks) {
                FlowElement taskActivity  = queryActivitiImplByTaskIdandActId(taskObj.getId(), taskObj.getTaskDefinitionKey());
                //20200106加判断只有不是多实例（会签）模式且环节类弄不是并行网关(parallelGateway)，才根据所传的人员来设置代理人，会签模式用生成的
                boolean isMultiInstance = isMultiInstance(taskActivity);//是否会签
                boolean isParallelGatewayInnerUserTask = isParallelGatewayInnerUserTask(taskObj.getProcessDefinitionId(), taskActivity.getId()); //是否是网关内的环节
                if (!"parallelGateway".contains(activityType) &&  isMultiInstance == false  && isParallelGatewayInnerUserTask == false) {
                    // 有传下一环节执行者时
                    if (assignees != null && assignees.size() > 0) {
                        // 删除设计器中初始的用户，以传的为准
                        taskService.setAssignee(taskObj.getId(), null);//有传人时，指定人也先删除
                        List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(taskObj.getId());
                        for (IdentityLink identityLink : identityLinks) {
                            if (!StringUtils.isEmpty(identityLink.getUserId())) {
                                taskService.deleteCandidateUser(taskObj.getId(), identityLink.getUserId());
                            }
                        }
                        if (assignees.size() == 1) {// 只有一个人时，直接设置到代理人中
                            taskService.setAssignee(taskObj.getId(), assignees.get(0).toString());
                        } else {// 多人加到候选人中
                            for (String assignee : assignees) {
                                taskService.addCandidateUser(taskObj.getId(), assignee);
                            }
                        }
                    }
                }
                if (priority != null) {
                    taskService.setPriority(taskObj.getId(), ((priority == 0) ? 1 : priority));
                }
                nextTaskId = taskObj.getId();
            }
        }
        // 记录实际审批人员，2022-02-19去掉记录实际审核人员，因为不需要记录了，方法改变了
        //actProcessService.insertActHiIdentityLink(UUID.randomUUID().toString(), FlowableConstant.EXECUTOR_TYPE, ShiroUtils.getMandatorId(), taskId, currentTask.getProcessInstanceId());
        sysProcessInstance.setPrevTaskId(taskId);
        sysProcessInstance.setNextTaskId(nextTaskId);
        sysProcessInstance.setDataStatus(FlowableConstant.STATUS_FINISH);
        sysProcessInstance.setResultStatus(FlowableConstant.RESULT_PASS);
        sysProcessInstance.setUpdateUser(ShiroUtils.getMandatorId());
        sysProcessInstance.setUpdateTime(new Date());
        sysProcessInstance.setActComment((comment.contains("同意") ? "":comment));
        setActivityCustomProperty(nextActivity, sysProcessInstance);
        sysProcessInstanceMapper.update(sysProcessInstance);
        if (softType.toLowerCase().contains("app")) {//只有app层调用时，才去更新业务表状态，其它层调用都各业务层去实现
            //更新相应业务表流程状态信息
            Map<String, Object> updateStateParams = new HashMap<>();
            updateStateParams.put("moduleTable", sysProcessInstance.getProcDefKey());
            updateStateParams.put("moduleNid", sysProcessInstance.getTableDataId());
            updateStateParams.put("activeFlow", sysProcessInstance.getNextActAlias());
            updateStateParams.put("procInstId", sysProcessInstance.getProcInstId());
            sysProcessInstanceMapper.updateActProcessModuleDataState(updateStateParams);
        }
        return new AjaxResult(AjaxResult.Type.SUCCESS, MessageUtils.message("module.success.issuccess"), nextActAlias);
    }

    @Override
    @Transactional
    public AjaxResult passAllProcess(String[] taskIds, Integer priority, String comment, String medium) {
       if(taskIds == null || taskIds.length == 0){
           return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "taskIds"));
       }
       for(String taskId : taskIds){
           Task task = queryTaskById(taskId);
           if (task == null) {
               return AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
           }
           if (task.isSuspended() == true){
               return AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
           }
           ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
           if (instance == null) {
               return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
           }
           SysProcessInstance sysProcessInstance = sysProcessInstanceMapper.findSysProcessInstanceByGuid(instance.getBusinessKey());
           if (sysProcessInstance == null) {
               return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
           }
           FlowElement nextActivity = queryCurrentTaskNextActivity(taskId);
           boolean isParallelGatewayInnerUserTask = false;
           String activityType = "";
           if (nextActivity != null){
               activityType = FlowableUtils.getFlowElementType(nextActivity);
               isParallelGatewayInnerUserTask = isParallelGatewayInnerUserTask(task.getProcessDefinitionId(), nextActivity.getId()); //是否是网关内的环节
           }
           List<SysUserInfoSimple> userInfoList  = queryNextTaskCandidateUsers(task.getProcessDefinitionId(), task.getId(), nextActivity, isParallelGatewayInnerUserTask);
           if(!"endEvent".contains(activityType) && (userInfoList == null || userInfoList.size() == 0)){
               return AjaxResult.error(MessageUtils.message("flowable.task.error.taskassigneesemptyfail", sysProcessInstance.getProcessTitle().toString()));
           }
           if (StringUtils.isEmpty(comment) || "null".contains(comment)) {
               comment = "同意";
           }
           //20220127创建流程备注改成自已写的命令
           //taskService.addComment(taskId, task.getProcessInstanceId(), comment);
           managementService.executeCommand(new AddTaskCommentCmd(taskId, task.getProcessInstanceId(), comment));
           // 未解决的委托任务先resolve
           if (StringUtils.isNotEmpty(task.getOwner()) && !("RESOLVED").equals(task.getDelegationState().toString())) {
               taskService.resolveTask(taskId);
           }
           // 接收任务(20200208当任务没有转办(owner为空)，才运行接收任务claim，已转办不接收，已转办人为准)
           if (StringUtils.isEmpty(task.getOwner())) {
               taskService.claim(taskId, ShiroUtils.getMandatorId());
           }
           String nextActAlias = "";
           // 设置上环节与下环节的信息
           if (nextActivity != null) {
               sysProcessInstance.setPrevActId(task.getTaskDefinitionKey());
               sysProcessInstance.setNextActId(nextActivity.getId());
               nextActAlias = getActivityAlias(nextActivity);
               sysProcessInstance.setNextActAlias(nextActAlias);
           }
           // 提交在deleteReason字段中标记
           managementService.executeCommand(new UpdateHiTaskReasonCommand(taskId, FlowableConstant.PASSED_FLAG));
           // 提交自已的任务
           Map<String, Object> variables = taskService.getVariables(taskId);
           if (variables == null) {
               variables = new HashMap<String, Object>();
           }
           variables.put("currentUserId", ShiroUtils.getMandatorId());
           taskService.complete(taskId, variables);
           // 获取下个环节的任务
           String nextTaskId = "";
           String nextActAssignees = "";
           List<Task> nextTasks = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
           if (nextTasks != null && nextTasks.size() > 0) {
               for (Task taskObj : nextTasks) {
                   FlowElement taskActivity  = queryActivitiImplByTaskIdandActId(taskObj.getId(), taskObj.getTaskDefinitionKey());
                   //20200106加判断只有不是多实例（会签）模式且环节类弄不是并行网关(parallelGateway)，才根据所传的人员来设置代理人，会签模式用生成的
                   boolean isMultiInstance = isMultiInstance(taskActivity);//是否会签
                   if (!"parallelGateway".contains(activityType) &&  isMultiInstance == false  && isParallelGatewayInnerUserTask == false) {
                       // 有传下一环节执行者时
                       if (userInfoList != null && userInfoList.size() > 0) {
                           // 删除设计器中初始的用户，以传的为准
                           taskService.setAssignee(taskObj.getId(), null);//有传人时，指定人也先删除
                           List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(taskObj.getId());
                           for (IdentityLink identityLink : identityLinks) {
                               if (!StringUtils.isEmpty(identityLink.getUserId())) {
                                   taskService.deleteCandidateUser(taskObj.getId(), identityLink.getUserId());
                               }
                           }
                           if (userInfoList.size() == 1) {// 只有一个人时，直接设置到代理人中
                               taskService.setAssignee(taskObj.getId(), userInfoList.get(0).getUserId());
                               nextActAssignees = userInfoList.get(0).getUserId()+ ",";
                           } else {// 多人加到候选人中
                               for (SysUserInfoSimple userInfoSimple : userInfoList) {
                                   taskService.addCandidateUser(taskObj.getId(), userInfoSimple.getUserId());
                                   nextActAssignees += userInfoSimple.getUserId() + ",";
                               }
                           }
                       }
                   }
                   if (priority != null) {
                       taskService.setPriority(taskObj.getId(), ((priority == 0) ? 1 : priority));
                   }
                   nextTaskId = taskObj.getId();
               }
           }
           // 记录实际审批人员，2022-02-19去掉记录实际审核人员，因为不需要记录了，方法改变了
           //actProcessService.insertActHiIdentityLink(UUID.randomUUID().toString(), FlowableConstant.EXECUTOR_TYPE, ShiroUtils.getMandatorId(), taskId, task.getProcessInstanceId());
           sysProcessInstance.setPrevTaskId(taskId);
           sysProcessInstance.setNextTaskId(nextTaskId);
           sysProcessInstance.setDataStatus(FlowableConstant.STATUS_FINISH);
           sysProcessInstance.setResultStatus(FlowableConstant.RESULT_PASS);
           sysProcessInstance.setUpdateUser(ShiroUtils.getMandatorId());
           sysProcessInstance.setUpdateTime(new Date());
           sysProcessInstance.setActComment((comment.contains("同意") ? "":comment));
           setActivityCustomProperty(nextActivity, sysProcessInstance);
           sysProcessInstanceMapper.update(sysProcessInstance);

           //更新相应业务表流程状态信息
           Map<String, Object> updateStateParams = new HashMap<>();
           updateStateParams.put("moduleTable", sysProcessInstance.getProcDefKey());
           updateStateParams.put("moduleNid", sysProcessInstance.getTableDataId());
           updateStateParams.put("activeFlow", nextActAlias);
           updateStateParams.put("procInstId", sysProcessInstance.getProcInstId());
           sysProcessInstanceMapper.updateActProcessModuleDataState(updateStateParams);

           //插入指定单据流转各环节审批人记录
           if (!StringUtils.isEmpty(nextActAssignees)){
               nextActAssignees = nextActAssignees.substring(0, nextActAssignees.length()-1);
           }
           Map<String, Object> flowRecord = new HashMap<String, Object>();
           flowRecord.put("moduleTable", sysProcessInstance.getProcDefKey());
           flowRecord.put("nid", sysProcessInstance.getTableDataId());
           flowRecord.put("activeFlowOld", sysProcessInstance.getPrevActId());
           flowRecord.put("activeFlow", sysProcessInstance.getNextActAlias());
           flowRecord.put("activeFlowName", sysProcessInstance.getNextActAlias());
           flowRecord.put("procInstId", sysProcessInstance.getProcInstId());
           flowRecord.put("createUser", ShiroUtils.getMandatorId());
           flowRecord.put("createUserName", ShiroUtils.getMandatorName());
           flowRecord.put("updateUsers", nextActAssignees);
           flowRecord.put("optType", "go");
           sysProcessInstanceMapper.insertProcessInstanceFlowRecord(flowRecord);
       }
       return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    @Override
    public AjaxResult backProcess(String taskId, Integer priority, String comment, List<String> assignees, Map<String, Object> variables, String medium, String softType) {
        if (StringUtils.isEmpty(taskId)) {
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "taskId"));
        }
        Task currentTask = queryTaskById(taskId);
        if (currentTask == null) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        if (currentTask.isSuspended() == true){
            return AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
        }
        ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult();
        if (instance == null) {
            return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        SysProcessInstance sysProcessInstance = sysProcessInstanceMapper.findSysProcessInstanceByGuid(instance.getBusinessKey());
        if (sysProcessInstance == null) {
            return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        // 找前一个节点
        FlowElement prevActivity = queryCurrentTaskPrevActivity(taskId, currentTask.getTaskDefinitionKey());
        if (prevActivity == null) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskactivityfail"));
        }
        String activityType = FlowableUtils.getFlowElementType(prevActivity);
        if("parallelGateway".contains(activityType)){
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskbackparallelgatewayfail"));
        }
        if ("startEvent".contains(activityType)) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskbackfail"));
        }
        if ((!"startEvent".contains(activityType) || !"endEvent".contains(activityType)) && (assignees == null || assignees.size() == 0)) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskassigneesfail"));
        }
        if (StringUtils.isEmpty(comment) || "null".contains(comment)) {
            comment = "退回";
        }
        //20220127创建流程备注改成自已写的命令
        //taskService.addComment(taskId, currentTask.getProcessInstanceId(), comment);
        managementService.executeCommand(new AddTaskCommentCmd(taskId, currentTask.getProcessInstanceId(), comment));
        // 接收任务
        taskService.claim(taskId, ShiroUtils.getMandatorId());
        // 实现本任务上环节跳转
        managementService.executeCommand(new RollbackTaskCmd(runtimeService, currentTask.getId(), prevActivity.getId(), FlowableConstant.BACKED_FLAG));
        // 获取下个环节的任务
        String nextTaskId = "";
        List<Task> nextTasks = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).list();
        if (nextTasks != null && nextTasks.size() > 0) {
            for (Task taskObj : nextTasks) {
                FlowElement taskActivity  = queryActivitiImplByTaskIdandActId(taskObj.getId(), taskObj.getTaskDefinitionKey());
                //20200106加判断只有不是多实例（会签）模式且环节类弄不是并行网关(parallelGateway)，才根据所传的人员来设置代理人，会签模式用生成的
                boolean isMultiInstance = isMultiInstance(taskActivity);//是否会签
                boolean isParallelGatewayInnerUserTask = isParallelGatewayInnerUserTask(taskObj.getProcessDefinitionId(), taskActivity.getId()); //是否是网关内的环节
                if (!"parallelGateway".contains(activityType) &&  isMultiInstance == false  && isParallelGatewayInnerUserTask == false) {
                    // 有传下一环节执行者时
                    if (assignees != null && assignees.size() > 0) {
                        // 删除设计器中初始的用户，以传的为准
                        taskService.setAssignee(taskObj.getId(), null);//有传人时，指定人也先删除
                        List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(taskObj.getId());
                        for (IdentityLink identityLink : identityLinks) {
                            if (!StringUtils.isEmpty(identityLink.getUserId())) {
                                taskService.deleteCandidateUser(taskObj.getId(), identityLink.getUserId());
                            }
                        }
                        if (assignees.size() == 1) {// 只有一个人时，直接设置到代理人中
                            taskService.setAssignee(taskObj.getId(), assignees.get(0).toString());
                        } else {// 多人加到候选人中
                            for (String assignee : assignees) {
                                taskService.addCandidateUser(taskObj.getId(), assignee);
                            }
                        }
                    }
                }
                if (priority != null) {
                    taskService.setPriority(taskObj.getId(), ((priority == 0) ? 1 : priority));
                }
                nextTaskId = taskObj.getId();
            }
        }
        // 记录实际审批人员，2022-02-19去掉记录实际审核人员，因为不需要记录了，方法改变了
        //actProcessService.insertActHiIdentityLink(UUID.randomUUID().toString(), FlowableConstant.EXECUTOR_TYPE, ShiroUtils.getMandatorId(), taskId, currentTask.getProcessInstanceId());
        String nextActAlias = "";
        sysProcessInstance.setPrevTaskId(taskId);
        sysProcessInstance.setNextTaskId(nextTaskId);
        // 设置上节点与下节点的信息
        sysProcessInstance.setPrevActId(currentTask.getTaskDefinitionKey());
        sysProcessInstance.setNextActId(prevActivity.getId());
        nextActAlias = getActivityAlias(prevActivity);
        sysProcessInstance.setNextActAlias(nextActAlias);
        sysProcessInstance.setDataStatus(FlowableConstant.STATUS_FINISH);
        sysProcessInstance.setResultStatus(FlowableConstant.RESULT_BACK);
        sysProcessInstance.setUpdateUser(ShiroUtils.getMandatorId());
        sysProcessInstance.setUpdateTime(new Date());
        sysProcessInstance.setActComment((comment.contains("退回") ? "":comment));
        setActivityCustomProperty(prevActivity, sysProcessInstance);
        sysProcessInstanceMapper.update(sysProcessInstance);
        if (softType.toLowerCase().contains("app")) {//只有app层调用时，才去更新业务表状态，其它层调用都各业务层去实现
            //更新相应业务表流程状态信息
            Map<String, Object> updateStateParams = new HashMap<>();
            updateStateParams.put("moduleTable", sysProcessInstance.getProcDefKey());
            updateStateParams.put("moduleNid", sysProcessInstance.getTableDataId());
            updateStateParams.put("activeFlow", sysProcessInstance.getNextActAlias());
            updateStateParams.put("procInstId", sysProcessInstance.getProcInstId());
            sysProcessInstanceMapper.updateActProcessModuleDataState(updateStateParams);
        }
        return new AjaxResult(AjaxResult.Type.SUCCESS, MessageUtils.message("module.success.issuccess"), nextActAlias);
    }

    @Override
    public AjaxResult backAllProcess(String[] taskIds, Integer priority, String comment, String medium) {
        if(taskIds == null || taskIds.length == 0){
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "taskIds"));
        }
        for(String taskId : taskIds) {
            Task task = queryTaskById(taskId);
            if (task == null) {
                return AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
            }
            if (task.isSuspended() == true) {
                return AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
            }
            ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            if (instance == null) {
                return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
            }
            SysProcessInstance sysProcessInstance = sysProcessInstanceMapper.findSysProcessInstanceByGuid(instance.getBusinessKey());
            if (sysProcessInstance == null) {
                return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
            }
            // 找前一个节点
            FlowElement prevActivity = queryCurrentTaskPrevActivity(taskId, task.getTaskDefinitionKey());
            if (prevActivity == null) {
                return AjaxResult.error(MessageUtils.message("flowable.task.error.taskactivityfail"));
            }
            String activityType = FlowableUtils.getFlowElementType(prevActivity);
            if("parallelGateway".contains(activityType)){
                return AjaxResult.error(MessageUtils.message("flowable.task.error.taskbackparallelgatewayfail"));
            }
            if ("startEvent".contains(activityType)) {
                return AjaxResult.error(MessageUtils.message("flowable.task.error.taskbackfail"));
            }
            List<SysUserInfoSimple> userInfoList = queryPrevTaskCandidateUsers(sysProcessInstance.getProcInstId(), prevActivity);
            if(userInfoList == null || userInfoList.size() == 0){
                return AjaxResult.error(MessageUtils.message("flowable.task.error.taskassigneesemptyfail"), sysProcessInstance.getProcessTitle());
            }
            if (StringUtils.isEmpty(comment) || "null".contains(comment)) {
                comment = "退回";
            }
            //20220127创建流程备注改成自已写的命令
            //taskService.addComment(taskId, task.getProcessInstanceId(), comment);
            managementService.executeCommand(new AddTaskCommentCmd(taskId, task.getProcessInstanceId(), comment));
            // 接收任务
            taskService.claim(taskId, ShiroUtils.getMandatorId());
            // 实现本任务上环节跳转
            managementService.executeCommand(new RollbackTaskCmd(runtimeService, task.getId(), prevActivity.getId(), FlowableConstant.BACKED_FLAG));
            // 获取下个环节的任务
            String nextTaskId = "";
            String nextActAssignees = "";
            List<Task> nextTasks = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
            if (nextTasks != null && nextTasks.size() > 0) {
                for (Task taskObj : nextTasks) {
                    FlowElement taskActivity  = queryActivitiImplByTaskIdandActId(taskObj.getId(), taskObj.getTaskDefinitionKey());
                    //20200106加判断只有不是多实例（会签）模式且环节类弄不是并行网关(parallelGateway)，才根据所传的人员来设置代理人，会签模式用生成的
                    boolean isMultiInstance = isMultiInstance(taskActivity);//是否会签
                    boolean isParallelGatewayInnerUserTask = isParallelGatewayInnerUserTask(taskObj.getProcessDefinitionId(), taskActivity.getId()); //是否是网关内的环节
                    if (!"parallelGateway".contains(activityType) &&  isMultiInstance == false  && isParallelGatewayInnerUserTask == false) {
                        // 有传下一环节执行者时
                        if (userInfoList != null && userInfoList.size() > 0) {
                            // 删除设计器中初始的用户，以传的为准
                            taskService.setAssignee(taskObj.getId(), null);//有传人时，指定人也先删除
                            List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(taskObj.getId());
                            for (IdentityLink identityLink : identityLinks) {
                                if (!StringUtils.isEmpty(identityLink.getUserId())) {
                                    taskService.deleteCandidateUser(taskObj.getId(), identityLink.getUserId());
                                }
                            }
                            if (userInfoList.size() == 1) {// 只有一个人时，直接设置到代理人中
                                taskService.setAssignee(taskObj.getId(), userInfoList.get(0).getUserId());
                                nextActAssignees = userInfoList.get(0).getUserId()+ ",";
                            } else {// 多人加到候选人中
                                for (SysUserInfoSimple userInfoSimple : userInfoList) {
                                    taskService.addCandidateUser(taskObj.getId(), userInfoSimple.getUserId());
                                    nextActAssignees += userInfoSimple.getUserId() + ",";
                                }
                            }
                        }
                    }
                    if (priority != null) {
                        taskService.setPriority(taskObj.getId(), ((priority == 0) ? 1 : priority));
                    }
                    nextTaskId = taskObj.getId();
                }
            }
            // 记录实际审批人员，2022-02-19去掉记录实际审核人员，因为不需要记录了，方法改变了
            //actProcessService.insertActHiIdentityLink(UUID.randomUUID().toString(), FlowableConstant.EXECUTOR_TYPE, ShiroUtils.getMandatorId(), taskId, task.getProcessInstanceId());
            String nextActAlias = "";
            sysProcessInstance.setPrevTaskId(taskId);
            sysProcessInstance.setNextTaskId(nextTaskId);
            // 设置上节点与下节点的信息
            sysProcessInstance.setPrevActId(task.getTaskDefinitionKey());
            sysProcessInstance.setNextActId(prevActivity.getId());
            nextActAlias = getActivityAlias(prevActivity);
            sysProcessInstance.setNextActAlias(nextActAlias);
            sysProcessInstance.setDataStatus(FlowableConstant.STATUS_FINISH);
            sysProcessInstance.setResultStatus(FlowableConstant.RESULT_BACK);
            sysProcessInstance.setUpdateUser(ShiroUtils.getMandatorId());
            sysProcessInstance.setUpdateTime(new Date());
            sysProcessInstance.setActComment((comment.contains("退回") ? "":comment));
            setActivityCustomProperty(prevActivity, sysProcessInstance);
            sysProcessInstanceMapper.update(sysProcessInstance);

            //更新相应业务表流程状态信息
            Map<String, Object> updateStateParams = new HashMap<>();
            updateStateParams.put("moduleTable", sysProcessInstance.getProcDefKey());
            updateStateParams.put("moduleNid", sysProcessInstance.getTableDataId());
            updateStateParams.put("activeFlow", nextActAlias);
            updateStateParams.put("procInstId", sysProcessInstance.getProcInstId());
            sysProcessInstanceMapper.updateActProcessModuleDataState(updateStateParams);

            //插入指定单据流转各环节审批人记录
            if (!StringUtils.isEmpty(nextActAssignees)){
                nextActAssignees = nextActAssignees.substring(0, nextActAssignees.length()-1);
            }
            Map<String, Object> flowRecord = new HashMap<String, Object>();
            flowRecord.put("moduleTable", sysProcessInstance.getProcDefKey());
            flowRecord.put("nid", sysProcessInstance.getTableDataId());
            flowRecord.put("activeFlowOld", sysProcessInstance.getPrevActId());
            flowRecord.put("activeFlow", sysProcessInstance.getNextActAlias());
            flowRecord.put("activeFlowName", sysProcessInstance.getNextActAlias());
            flowRecord.put("procInstId", sysProcessInstance.getProcInstId());
            flowRecord.put("createUser", ShiroUtils.getMandatorId());
            flowRecord.put("createUserName", ShiroUtils.getMandatorName());
            flowRecord.put("updateUsers", nextActAssignees);
            flowRecord.put("optType", "back");
            sysProcessInstanceMapper.insertProcessInstanceFlowRecord(flowRecord);
        }
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    @Override
    public AjaxResult resetBackProcess(String nid, String activityId, Integer priority, String comment, List<String> assignees, String medium, String softType) {
        if (StringUtils.isEmpty(nid)) {
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "nid"));
        }
        SysProcessInstance sysProcessInstance = sysProcessInstanceMapper.findSysProcessInstanceByTableDataId(nid);
        if (sysProcessInstance == null){
            return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        String businessKey = sysProcessInstance.getGuid();
        String assignee = sysProcessInstance.getOrganizer();
        String oldProcInstId = sysProcessInstance.getProcInstId();
        identityService.setAuthenticatedUserId(assignee);
        Map<String, Object> variables = sysProcessInstance.getParams();
        if (variables == null) {
            variables = new HashMap<String, Object>();
        }
        //注册Juel表达式类
        variables.put("authService", new ActAuthService());
        variables.put("moduleKey", sysProcessInstance.getProcDefKey());
        variables.put("tableDataId", sysProcessInstance.getTableDataId());
        variables.put("currentUserId", assignee);

        ProcessInstance processInstance = runtimeService.startProcessInstanceById(sysProcessInstance.getProcDefId(), businessKey, variables);
        String processInstanceId = processInstance.getId();
        sysProcessInstance.setProcInstId(processInstanceId);
        sysProcessInstance.setProcDefId(processInstance.getProcessDefinitionId());
        sysProcessInstance.setProcDefKey(processInstance.getProcessDefinitionKey());
        //取流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()).singleResult();
        if (processDefinition != null){
            sysProcessInstance.setProcDefName(processDefinition.getName());
            sysProcessInstance.setProcDefVersion(processDefinition.getVersion());
            sysProcessInstance.setProcDeplId(processDefinition.getDeploymentId());
        }
        setResetProcessTask(processInstanceId, oldProcInstId, activityId, sysProcessInstance, priority,assignees);
        //更新原来旧的数据到新的流程实例下
        try{
            Map<String, Object> updatePrams = new HashMap<>();
            updatePrams.put("newProcInstId", processInstanceId);
            updatePrams.put("oldProcInstId", oldProcInstId);
            actProcessMapper.updateActHiTaskProcInstData(updatePrams);
        }catch (Exception ex){
        }
        if (StringUtils.isEmpty(comment) || "null".contains(comment)) {
            comment = "重置退回";
        }
        //重置流程设置
        sysProcessInstance.setStartFlowTime(new Date());
        sysProcessInstance.setDataStatus(0);
        sysProcessInstance.setResultStatus(0);
        sysProcessInstance.setUpdateUser(ShiroUtils.getMandatorId());
        sysProcessInstance.setUpdateTime(new Date());
        sysProcessInstance.setActComment((comment.contains("重置退回") ? "":comment));
        FlowElement targetActivity = queryActivitiImplByProDefIdandActId(sysProcessInstance.getProcDefId(), activityId);
        setActivityCustomProperty(targetActivity, sysProcessInstance);
        sysProcessInstanceMapper.updateResetProcess(sysProcessInstance);
        if (softType.toLowerCase().contains("app")) {//只有app层调用时，才去更新业务表状态，其它层调用都各业务层去实现
            //更新相应业务表流程状态信息
            Map<String, Object> updateStateParams = new HashMap<>();
            updateStateParams.put("moduleTable", sysProcessInstance.getProcDefKey());
            updateStateParams.put("moduleNid", sysProcessInstance.getTableDataId());
            updateStateParams.put("activeFlow", sysProcessInstance.getNextActAlias());
            updateStateParams.put("procInstId", sysProcessInstance.getProcInstId());
            sysProcessInstanceMapper.updateActProcessModuleDataState(updateStateParams);
        }
        Map<String, Object> backPrams = new HashMap<>();
        backPrams.put("procInstId", processInstanceId);
        backPrams.put("activeFlow", sysProcessInstance.getNextActAlias());
        return new AjaxResult(AjaxResult.Type.SUCCESS, MessageUtils.message("module.success.issuccess"), backPrams);
    }

    //设置重置流程任务人员与自动提交
    private void setResetProcessTask(String newProcInstId, String oldProcInstId, String targetActId, SysProcessInstance sysProcessInstance, Integer priority, List<String> assignees){
        //查询这个实例运行中的任务
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(newProcInstId).list();
        //启动时设置首个任务信息
        for(Task taskObj : taskList) {
            if (taskObj.getTaskDefinitionKey().equals(targetActId)) {
                sysProcessInstance.setNextTaskId(taskObj.getId());
                sysProcessInstance.setNextActId(taskObj.getTaskDefinitionKey());
                sysProcessInstance.setNextActAlias(taskObj.getTaskDefinitionKey());
                // 设置任务优先级
                taskService.setPriority(taskObj.getId(), priority);
                if("flowzd".equals(taskObj.getTaskDefinitionKey().toLowerCase())){//如果为制单环节，这边直接设置人
                    //删除制单环节在设计器中设置的候选人、候选组等配置
                    actProcessService.deleteFirstSegmentUserExpression(taskObj);
                }
                // 有传下一环节执行者时
                if (assignees != null && assignees.size() > 0) {
                    // 删除设计器中初始的用户，以传的为准
                    taskService.setAssignee(taskObj.getId(), null);//有传人时，指定人也先删除
                    List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(taskObj.getId());
                    for (IdentityLink identityLink : identityLinks) {
                        if (!StringUtils.isEmpty(identityLink.getUserId())) {
                            taskService.deleteCandidateUser(taskObj.getId(), identityLink.getUserId());
                        }
                    }
                    if (assignees.size() == 1) {// 只有一个人时，直接设置到代理人中
                        taskService.setAssignee(taskObj.getId(), assignees.get(0).toString());
                    } else {// 多人加到候选人中
                        for (String assignee : assignees) {
                            taskService.addCandidateUser(taskObj.getId(), assignee);
                        }
                    }
                }
                return;
            } else {
                String oldAssignee = "";
                String oldComment = "";
                org.flowable.bpmn.model.Process process = repositoryService.getBpmnModel(taskObj.getProcessDefinitionId()).getMainProcess();
                FlowElement taskActivity = (FlowNode) process.getFlowElement(taskObj.getTaskDefinitionKey(), true);
                //20200106加判断只有不是多实例（会签）模式且环节类弄不是并行网关(parallelGateway)，才根据所传的人员来设置代理人，会签模式用生成的
                boolean isMultiInstance = isMultiInstance(taskActivity);//是否会签
                boolean isParallelGatewayInnerUserTask = isParallelGatewayInnerUserTask(taskObj.getProcessDefinitionId(), taskActivity.getId()); //是否是网关内的环节
                if (isMultiInstance == false && isParallelGatewayInnerUserTask == false) {
                    HistoricTaskInstance oldTaskInstance = null;
                    List<HistoricTaskInstance> historicTaskInstanceList =  historyService.createHistoricTaskInstanceQuery().processInstanceId(oldProcInstId).taskDefinitionKey(taskActivity.getId()).taskDeleteReason(FlowableConstant.PASSED_FLAG).finished().orderByHistoricTaskInstanceStartTime().desc().list();
                    if(historicTaskInstanceList != null && historicTaskInstanceList.size() > 0){
                        oldTaskInstance = historicTaskInstanceList.get(0);
                    }
                    if (oldTaskInstance != null) {
                        // 删除设计器中初始的用户，以传的为准
                        List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(taskObj.getId());
                        for (IdentityLink identityLink : identityLinks) {
                            if (!StringUtils.isEmpty(identityLink.getUserId())) {
                                taskService.deleteCandidateUser(taskObj.getId(), identityLink.getUserId());
                            }
                        }
                        taskService.setAssignee(taskObj.getId(), oldTaskInstance.getAssignee());
                        oldAssignee = oldTaskInstance.getAssignee();
                        List<Comment> comment = taskService.getTaskComments(oldTaskInstance.getId(), "comment");
                        if (!CollectionUtils.isEmpty(comment)) {
                            oldComment = comment.get(0).getFullMessage();
                        }
                    }
                } else {
                    oldAssignee = taskObj.getAssignee();
                    HistoricTaskInstance oldTaskInstance = null;
                    List<HistoricTaskInstance> historicTaskInstanceList =  historyService.createHistoricTaskInstanceQuery().processInstanceId(oldProcInstId).taskDefinitionKey(taskActivity.getId()).taskAssignee(oldAssignee).taskDeleteReason(FlowableConstant.PASSED_FLAG).finished().orderByHistoricTaskInstanceStartTime().desc().list();
                    if(historicTaskInstanceList != null && historicTaskInstanceList.size() > 0){
                        oldTaskInstance = historicTaskInstanceList.get(0);
                    }
                    if(oldTaskInstance != null){
                        List<Comment> comment = taskService.getTaskComments(oldTaskInstance.getId(), "comment");
                        if (!CollectionUtils.isEmpty(comment)) {
                            oldComment = comment.get(0).getFullMessage();
                        }
                    }
                }
                sysProcessInstance.setPrevTaskId(taskObj.getId());
                sysProcessInstance.setPrevActId(taskObj.getTaskDefinitionKey());
                //20220127创建流程备注改成自已写的命令
                //taskService.addComment(taskObj.getId(), taskObj.getProcessInstanceId(),  (StringUtils.isEmpty(oldComment) ? "同意" : oldComment));
                managementService.executeCommand(new AddTaskCommentCmd(taskObj.getId(), taskObj.getProcessInstanceId(),  (StringUtils.isEmpty(oldComment) ? "同意" : oldComment)));
                // 未解决的委托任务先resolve
                if (StringUtils.isNotEmpty(taskObj.getOwner()) && !("RESOLVED").equals(taskObj.getDelegationState().toString())) {
                    taskService.resolveTask(taskObj.getId());
                }
                // 接收任务(20200208当任务没有转办(owner为空)，才运行接收任务claim，已转办不接收，已转办人为准)
                if (StringUtils.isEmpty(taskObj.getOwner())) {
                    taskService.claim(taskObj.getId(), oldAssignee);
                }
                // 提交在deleteReason字段中标记
                managementService.executeCommand(new UpdateHiTaskReasonCommand(taskObj.getId(), FlowableConstant.AUTOPASSED_FLAG));
                Map<String, Object> variables = new HashMap<String, Object>();
                variables = taskService.getVariables(taskObj.getId());
                variables.put("currentUserId", oldAssignee);
                taskService.setPriority(taskObj.getId(), 1);
                taskService.complete(taskObj.getId(), variables);
            }
        }
        setResetProcessTask(newProcInstId, oldProcInstId, targetActId, sysProcessInstance, priority, assignees);
        return;
    }

    @Override
    public AjaxResult rejectProcess(String taskId, String activityId, Integer priority, String comment, List<String> assignees, Map<String, Object> variables, String medium, String softType) {
        if (StringUtils.isEmpty(taskId)) {
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "taskId"));
        }
        if (assignees == null || assignees.size() == 0) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskassigneesfail"));
        }
        if (StringUtils.isEmpty(activityId)) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskactivityfail"));
        }
        Task currentTask = queryTaskById(taskId);
        if (currentTask == null) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        if (currentTask.isSuspended() == true){
            return AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
        }
        ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult();
        if (instance == null) {
            return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        SysProcessInstance sysProcessInstance = sysProcessInstanceMapper.findSysProcessInstanceByGuid(instance.getBusinessKey());
        if (sysProcessInstance == null) {
            return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        FlowElement targetActivity = queryActivitiImplByTaskIdandActId(taskId, activityId);
        String activityType = FlowableUtils.getFlowElementType(targetActivity);
        if(targetActivity instanceof  ParallelGateway){
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskbackparallelgatewayfail"));
        }
        if (targetActivity instanceof  StartEvent) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskbackfail"));
        }
        if ((!(targetActivity instanceof  StartEvent) || !(targetActivity instanceof  EndEvent)) && (assignees == null || assignees.size() == 0)) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskassigneesfail"));
        }
        if (StringUtils.isEmpty(comment) || "null".contains(comment)) {
            comment = "驳回";
        }
        //20220127创建流程备注改成自已写的命令
        //taskService.addComment(taskId, currentTask.getProcessInstanceId(), comment);
        managementService.executeCommand(new AddTaskCommentCmd(taskId, currentTask.getProcessInstanceId(), comment));
        //接收任务(20200216去掉这个，因为管理员需要处理不是自已任务的数据)
        //taskService.claim(taskId, ShiroUtils.getMandatorId());
        // 设置上环节与下环节的信息
        String nextActAlias = "";
        if (targetActivity != null) {
            sysProcessInstance.setPrevActId(currentTask.getTaskDefinitionKey());
            sysProcessInstance.setNextActId(targetActivity.getId());
            nextActAlias = getActivityAlias(targetActivity);
            sysProcessInstance.setNextActAlias(nextActAlias);
        }
        // 实现跳转
        managementService.executeCommand(new RollbackTaskCmd(runtimeService, currentTask.getId(), activityId, FlowableConstant.REJECTED_FLAG));
        // 获取下个环节的任务
        String nextTaskId = "";
        List<Task> nextTasks = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).list();
        if (nextTasks != null && nextTasks.size() > 0) {
            for (Task taskObj : nextTasks) {
                FlowElement taskActivity  = queryActivitiImplByTaskIdandActId(taskObj.getId(), taskObj.getTaskDefinitionKey());
                //20200106加判断只有不是多实例（会签）模式且环节类弄不是并行网关(parallelGateway)，才根据所传的人员来设置代理人，会签模式用生成的
                boolean isMultiInstance = isMultiInstance(taskActivity);//是否会签
                boolean isParallelGatewayInnerUserTask = isParallelGatewayInnerUserTask(taskObj.getProcessDefinitionId(), taskActivity.getId()); //是否是网关内的环节
                if (!"parallelGateway".contains(activityType) &&  isMultiInstance == false  && isParallelGatewayInnerUserTask == false) {
                    if (assignees != null && assignees.size() > 0) {
                        // 删除设计器中初始的用户，以传的为准
                        taskService.setAssignee(taskObj.getId(), null);//有传人时，指定人也先删除
                        List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(taskObj.getId());
                        for (IdentityLink identityLink : identityLinks) {
                            if (!StringUtils.isEmpty(identityLink.getUserId())) {
                                taskService.deleteCandidateUser(taskObj.getId(), identityLink.getUserId());
                            }
                        }
                        if (assignees.size() == 1) {// 只有一个人时，直接设置到代理人中
                            taskService.setAssignee(taskObj.getId(), assignees.get(0).toString());
                        } else {// 多人加到候选人中
                            for (String assignee : assignees) {
                                taskService.addCandidateUser(taskObj.getId(), assignee);
                            }
                        }
                    }
                }
                if (priority != null) {
                    taskService.setPriority(taskObj.getId(), ((priority == 0) ? 1 : priority));
                }
                nextTaskId = taskObj.getId();
            }
        }
        // 记录实际审批人员，2022-02-19去掉记录实际审核人员，因为不需要记录了，方法改变了
        //actProcessService.insertActHiIdentityLink(UUID.randomUUID().toString(), FlowableConstant.EXECUTOR_TYPE, ShiroUtils.getMandatorId(), taskId, currentTask.getProcessInstanceId());
        sysProcessInstance.setPrevTaskId(taskId);
        sysProcessInstance.setNextTaskId(nextTaskId);
        sysProcessInstance.setNextActAlias(nextActAlias);
        sysProcessInstance.setDataStatus(FlowableConstant.STATUS_FINISH);
        sysProcessInstance.setResultStatus(FlowableConstant.RESULT_REJECT);
        sysProcessInstance.setUpdateUser(ShiroUtils.getMandatorId());
        sysProcessInstance.setUpdateTime(new Date());
        sysProcessInstance.setActComment((comment.contains("驳回") ? "":comment));
        setActivityCustomProperty(targetActivity, sysProcessInstance);
        sysProcessInstanceMapper.update(sysProcessInstance);
        if (softType.toLowerCase().contains("app")) {//只有app层调用时，才去更新业务表状态，其它层调用都各业务层去实现
            //更新相应业务表流程状态信息
            Map<String, Object> updateStateParams = new HashMap<>();
            updateStateParams.put("moduleTable", sysProcessInstance.getProcDefKey());
            updateStateParams.put("moduleNid", sysProcessInstance.getTableDataId());
            updateStateParams.put("activeFlow", sysProcessInstance.getNextActAlias());
            updateStateParams.put("procInstId", sysProcessInstance.getProcInstId());
            sysProcessInstanceMapper.updateActProcessModuleDataState(updateStateParams);
        }
        return new AjaxResult(AjaxResult.Type.SUCCESS, MessageUtils.message("module.success.issuccess"), nextActAlias);
    }

    @Override
    public AjaxResult endProcess(String taskId, String comment) {
        if (StringUtils.isEmpty(taskId)) {
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "taskId"));
        }
        Task currentTask = queryTaskById(taskId);
        if (currentTask == null) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        if (currentTask.isSuspended() == true){
            return AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
        }
        ProcessInstance instance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(currentTask.getProcessInstanceId()).singleResult();
        if (instance == null) {
            return AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        if (StringUtils.isEmpty(comment) || "null".contains(comment)) {
            comment = "同意";
        }
        if (!StringUtils.isEmpty(comment)) {
            //20220127创建流程备注改成自已写的命令
            //taskService.addComment(taskId, currentTask.getProcessInstanceId(), comment);
            managementService.executeCommand(new AddTaskCommentCmd(taskId, currentTask.getProcessInstanceId(), comment));
        }
        FlowElement endActivity = queryActivitiImplByTaskIdandActId(taskId, "end");
        // 接收任务
        taskService.claim(taskId, ShiroUtils.getMandatorId());
        //中止实现跳转,并在deleteReason字段中标记
        managementService.executeCommand(new JumpTaskCommand(runtimeService, currentTask.getProcessInstanceId(), endActivity.getId(), FlowableConstant.ENDED_FLAG));
        SysProcessInstance sysProcessInstance = sysProcessInstanceMapper.findSysProcessInstanceByGuid(instance.getBusinessKey());
        if (sysProcessInstance != null) {
            sysProcessInstance.setDataStatus(FlowableConstant.STATUS_FINISH);
            sysProcessInstance.setResultStatus(FlowableConstant.RESULT_END);
            sysProcessInstance.setUpdateUser(ShiroUtils.getMandatorId());
            sysProcessInstance.setUpdateTime(new Date());
            sysProcessInstance.setActComment((comment.contains("同意") ? "":comment));
            setActivityCustomProperty(endActivity, sysProcessInstance);
            sysProcessInstanceMapper.update(sysProcessInstance);
        }
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    @Override
    public AjaxResult jointProcess(String taskId, List<String> users) {
        if (StringUtils.isEmpty(taskId)) {
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "taskId"));
        }
        Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (currentTask == null) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        if (currentTask.isSuspended() == true){
            return AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
        }
        for (String userId : users) {
            runtimeService.addMultiInstanceExecution(currentTask.getTaskDefinitionKey(), currentTask.getProcessInstanceId(), Collections.singletonMap("assignee", (Object) userId));
        }
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    @Override
    public AjaxResult transferProcess(String taskId, String userId) {
        if (StringUtils.isEmpty(taskId)) {
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "taskId"));
        }
        if (StringUtils.isEmpty(userId)) {
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "userId"));
        }
        Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (currentTask == null) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        if (currentTask.isSuspended() == true){
            return AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
        }
        taskService.setAssignee(taskId, userId);
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    @Override
    public AjaxResult delegateProcess(String taskId, String userId, String comment) {
        if (StringUtils.isEmpty(taskId)) {
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "taskId"));
        }
        if (StringUtils.isEmpty(userId)) {
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "userId"));
        }
        Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (currentTask == null) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        if (currentTask.isSuspended() == true){
            return AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
        }
        if("flowzd".equals(currentTask.getTaskDefinitionKey().toLowerCase())){
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskdelegatestartactfail"));
        }
        ProcessInstance instance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(currentTask.getProcessInstanceId()).singleResult();
        if (instance == null) {
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        if (StringUtils.isEmpty(comment) || "null".contains(comment)) {
            comment = "同意";
        }
        if (!StringUtils.isEmpty(comment)) {
            //20220127创建流程备注改成自已写的命令
            //taskService.addComment(taskId, currentTask.getProcessInstanceId(), comment);
            managementService.executeCommand(new AddTaskCommentCmd(taskId, currentTask.getProcessInstanceId(), comment));
        }
        taskService.delegateTask(taskId, userId);
        taskService.setOwner(taskId, ShiroUtils.getMandatorId());
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    @Override
    public String queryActivitiImplNameByNid(String nid) {
        String activitiName = MessageUtils.message("flowable.task.error.taskactivitynamefail");
        if(StringUtils.isEmpty(nid)){
            return  activitiName;
        }
        SysProcessInstance sysProcessInstance = querySysProcessInstanceByTableDataId(nid);
        if(sysProcessInstance == null){
            return  activitiName;
        }
        FlowElement curActivity = null;
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(sysProcessInstance.getProcInstId()).list();
        Task curtTask =  null;
        if(taskList != null && taskList.size() > 0){
            curtTask = taskList.get(0);
        }
        //先取当前任务，没有任务才用sysProcessInstance对象中的NextActId值
        if(curtTask != null){
            curActivity = queryActivitiImplByProDefIdandActId(curtTask.getProcessDefinitionId(), curtTask.getTaskDefinitionKey());
        }
        else {
            try {
                curActivity = queryActivitiImplByProDefIdandActId(sysProcessInstance.getProcDefId(), sysProcessInstance.getNextActId());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        if(curActivity != null){
            String type = FlowableUtils.getFlowElementType(curActivity);
            activitiName = curActivity.getName();
            if ("startEvent".contains(type)) {// 判断开始环节
                activitiName = MessageUtils.message("flowable.proces.startstatename");
            }else if ("endEvent".contains(type)) {// 判断结束环节
                activitiName = MessageUtils.message("flowable.process.endstatename");
            }if ("parallelGateway".contains(type)) {
                Task multiTask = queryUserCurrentInstanceRunTask(sysProcessInstance.getProcInstId(), ShiroUtils.getMandatorId());
                if (multiTask != null){
                    curActivity = queryActivitiImplByProDefIdandActId(multiTask.getProcessDefinitionId(), multiTask.getTaskDefinitionKey());
                    if(curActivity != null){
                        activitiName = curActivity.getName();
                    }
                }else{
                    activitiName = MessageUtils.message("flowable.process.parallelgatewaystatename");
                }
            }
        }
        return activitiName;
    }

    @Override
    public boolean isMultiInstance(FlowElement flowElement) {
        FlowNode flowNode = (FlowNode) flowElement;
       if(flowNode != null && flowNode.getBehavior() instanceof MultiInstanceActivityBehavior ){
           return  true;
       }
       return  false;
    }

    /**
     * 判断某个UserTask是否是网关内的用户节点
     * @param procDefId
     * @param activityId
     * @return
     */
    @Override
    public  boolean isParallelGatewayInnerUserTask(String procDefId, String activityId){
        org.flowable.bpmn.model.Process process = repositoryService.getBpmnModel(procDefId).getMainProcess();
        Map<String, Set<String>> specialGatewayNodes = FlowableUtils.getSpecialGatewayElements(process);
        if(specialGatewayNodes != null && specialGatewayNodes.size() > 0){
            for(Map.Entry<String, Set<String>> entry : specialGatewayNodes.entrySet()){
                String mapKey = entry.getKey();
                Set<String> specialGatewayList = (Set<String>)specialGatewayNodes.get(mapKey);
                if(specialGatewayList != null && specialGatewayList.size() > 0 && specialGatewayList.equals(activityId)){
                    return  true;
                }
            }
        }
        return  false;
    }

    @Override
    public boolean isCanProcessEndBack(String nid, String curUserId) {
        boolean result = false;
        SysProcessInstance sysProcessInstance = querySysProcessInstanceByTableDataId(nid);
        if(sysProcessInstance == null){
            return result;
        }
        List<HistoricTaskInstance> historicTaskInstanceList =  historyService.createHistoricTaskInstanceQuery().processInstanceId(sysProcessInstance.getProcInstId()).taskDefinitionKey(sysProcessInstance.getPrevActId()).taskDeleteReason(FlowableConstant.PASSED_FLAG).finished().orderByHistoricTaskInstanceStartTime().desc().list();
        if(historicTaskInstanceList != null && historicTaskInstanceList.size() > 0){
            for (HistoricTaskInstance item : historicTaskInstanceList) {
                if(item.getAssignee().equals(curUserId)){
                    result = true;
                    break;
                }
            }
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> queryUserWithWeChatId() {
        return actProcessMapper.findUserWithWeChatId();
    }

    @Override
    public AjaxResult updateTaskWxSendFlag(List<String> idList) {
        if (idList == null && idList.size() == 0) {
            return AjaxResult.error("请提供必要的参数[idList]");
        }else {
            Map<String, Object> params = new HashMap<>();
            params.put("ids", idList);
            actProcessMapper.updateTaskWxSendFlag(params);
            return AjaxResult.success("操作成功");
        }
    }

    /**
     * 根据任务Id，获取某个环节对象信息
     * @param taskId
     * @param activityId
     * @return
     */
    private FlowElement queryActivitiImplByTaskIdandActId(String taskId, String activityId) {
        Task task = queryTaskById(taskId);
        if (task == null) {
            return null;
        }
        // 获取当前活动节点ID
        if (StringUtils.isEmpty(activityId)) {
            activityId = task.getTaskDefinitionKey();
        }
        org.flowable.bpmn.model.Process process = repositoryService.getBpmnModel(task.getProcessDefinitionId()).getMainProcess();
        FlowElement currentFlowElement = (FlowNode) process.getFlowElement(activityId, true);
        return currentFlowElement;
    }


    /**
     * 获取节点的别名，对开始与结束环节特列命名
     *
     * @param flowElement
     * @return
     */
    private String getActivityAlias(FlowElement flowElement) {
        String result = "";
        if (flowElement == null) {
            return "";
        }
        if(flowElement instanceof StartEvent){
            result= "start";
        }else if(flowElement instanceof EndEvent){
            result=   "end";
        }else {
            result = flowElement.getId();
        }
        return result;
    }

    /**
     * 将自定义的环节属性存到SysProcessInstance对象中
     *
     * @param flowElement
     * @return
     */
    private SysProcessInstance setActivityCustomProperty(FlowElement flowElement, SysProcessInstance sysProcessInstance){
        //到下一个环节赋值时，先赋空，再赋值
        sysProcessInstance.setActFuncKey("");
        sysProcessInstance.setActFormPage("");
        sysProcessInstance.setActFuncIsEdit(false);
        if(flowElement instanceof  UserTask) {
            UserTask userTaskNode = (UserTask) flowElement;
            Map<String, List<ExtensionAttribute>> extensionAttrs = userTaskNode.getAttributes();
            if (extensionAttrs != null && extensionAttrs.size() > 0) {
                List<ExtensionAttribute> extensionAttributeList1 = extensionAttrs.get(FlowableConstant.CUSTOM_AUDIT_FUNCTIONKEY_KEY);
                if (extensionAttributeList1 != null && extensionAttributeList1.size() > 0) {
                    sysProcessInstance.setActFuncKey(extensionAttributeList1.get(0).getValue());
                }
                List<ExtensionAttribute> extensionAttributeList2 = extensionAttrs.get(FlowableConstant.CUSTOM_AUDIT_FORMPAGE_KEY);
                if (extensionAttributeList2 != null && extensionAttributeList2.size() > 0) {
                    sysProcessInstance.setActFormPage(extensionAttributeList2.get(0).getValue());
                }
                List<ExtensionAttribute> extensionAttributeList3 = extensionAttrs.get(FlowableConstant.CUSTOM_AUDIT_FUNCTIONEDIT_KEY);
                if (extensionAttributeList3 != null && extensionAttributeList3.size() > 0) {
                    sysProcessInstance.setActFuncIsEdit(TypeUtils.getSafeBool(extensionAttributeList3.get(0).getValue(), false));
                }
            }
        }
        return  sysProcessInstance;
    }

    /**
     * 根据key和value判断el表达式是否通过信息 
     * * @param String key    el表达式key信息 
     * * @param String el     el表达式信息 
     * * @return
     */
    private boolean isCondition(String key, String el, Map<String, Object> mapVars) {
        ExpressionFactory factory = new ExpressionFactoryImpl();
        SimpleContext context = new SimpleContext();
        //20200117判断表达式时，每次这边修改当前用户currentUserId值
        mapVars.put("currentUserId", ShiroUtils.getMandatorId());
        for (Map.Entry<String, Object> entry : mapVars.entrySet()) {
            context.setVariable(entry.getKey(), factory.createValueExpression(entry.getValue(), getValueClass(entry.getValue())));
        }
        ValueExpression e = factory.createValueExpression(context, el, boolean.class);
        return (Boolean) e.getValue(context);
    }

    /**
     * * @Title: getValueClass
     * * @Description: TODO(根据值获取值类型)
     * * @param obj
     * * @return
     * * @return Class<?> (这里用一句话描述返回结果说明)  
     */
    private Class<?> getValueClass(Object obj) {
        if (obj instanceof Boolean) {
            return Boolean.class;
        } else if (obj instanceof Integer) {
            return Integer.class;
        } else if (obj instanceof String) {
            return String.class;
        } else if (obj instanceof Long) {
            return Long.class;
        } else if (obj instanceof Map) {
            return Map.class;
        } else if (obj instanceof Collection) {
            return Collection.class;
        } else if (obj instanceof java.util.List) {
            return java.util.List.class;
        } else if (obj instanceof ActAuthService) {
            return ActAuthService.class;
        } else if (obj instanceof SysProcessInstanceMapper) {
            return SysProcessInstanceMapper.class;
        }  else {
            return String.class;
        }
    }
}
